package com.bwda.dsrs.base.util;

import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.params.KeyParameter;

import java.nio.charset.Charset;

/**
 * 3DES加密
 *
 * @author yanyuemei
 */
public class ThreeDesUtil {

    private static final byte[] HEX_DIGITS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70};

    private static final int INT8 = 8;
    private static final int INT2 = 2;

    /**
     * 原秘钥ey(Ai58!
     */
    private static final String KEY = "6#dPz>3F";

    private static DESEngine cipher = new DESEngine();

    private static byte[] groupingEncrypt(byte[] key, byte[] data) {
        int iRet = data.length % 8;
        byte[] out;
        if (iRet > 0) {
            int length = data.length + (8 - iRet);
            out = new byte[length];
        } else {
            out = new byte[data.length];
        }
        cipher.init(true, new KeyParameter(key));
        int i;
        for (i = 0; i < data.length / INT8; i++) {
            cipher.processBlock(data, i * 8, out, i * 8);
        }
        if (iRet > 0) {
            byte[] temp = new byte[8];
            System.arraycopy(data, i * 8, temp, 0, iRet);
            temp[iRet] = -128;
            cipher.processBlock(temp, 0, out, i * 8);
        }
        byte[] toasc = new byte[out.length * 2];
        int k = 0;
        int j = 0;
        for (i = 0; i < out.length; i++) {
            k = out[i];
            toasc[j++] = HEX_DIGITS[k >>> 4 & 0xf];
            toasc[j++] = HEX_DIGITS[k & 0xf];
        }

        return toasc;
    }

    private static byte[] groupingDecrypt(byte[] key, byte[] data) {
        int k = 0;
        byte[] tobyte = new byte[data.length / 2];
        for (int i = 0; i < data.length; i += INT2) {
            char ch;
            if (data[i] <= 57) {
                ch = (char) (data[i] & 0xf);
            } else {
                ch = (char) ((data[i] & 0xf) + 9);
            }
            ch <<= '\004';
            if (data[i + 1] <= 57) {
                ch |= data[i + 1] & 0xf;
            } else {
                ch |= (data[i + 1] & 0xf) + 9;
            }
            tobyte[k] = (byte) ch;
            k++;
        }

        cipher.init(false, new KeyParameter(key));
        if (tobyte.length % INT8 == 0) {
            byte[] out = new byte[tobyte.length];
            for (int i = 0; i < tobyte.length / INT8; i++) {
                cipher.processBlock(tobyte, i * 8, out, i * 8);
            }
            int len = padCount(out);
            byte[] deout = new byte[out.length - len];
            System.arraycopy(out, 0, deout, 0, out.length - len);
            return deout;
        } else {
            return null;
        }
    }

    private static int padCount(byte[] in) {
        int count;
        for (count = in.length; count > 0; count--) {
            if (in[count - 1] != 0) {
                break;
            }
        }

        int i128 = -128;
        if (in[count - 1] == i128) {
            return (in.length - count) + 1;
        } else {
            return in.length - count;
        }
    }

    /**
     * 加密
     *
     * @param code
     * @return
     */
    public final static String encode(String code) {
        if (code == null) {
            return null;
        } else {
            Charset charset = Charset.forName("UTF-8");
            byte[] cryptogragh = groupingEncrypt(KEY.getBytes(charset), code.getBytes(charset));
            return new String(cryptogragh, charset);
        }
    }

    /**
     * 解密
     *
     * @param code
     * @return
     */
    public final static String decode(String code) {
        if (code == null) {
            return null;
        } else {
            Charset charset = Charset.forName("UTF-8");
            byte[] debyte = groupingDecrypt(KEY.getBytes(charset), code.getBytes(charset));
            return debyte != null ? new String(debyte, charset) : null;
        }
    }

    public static void main(String[] args) {
        System.out.println(ThreeDesUtil.encode("dsrs"));
        System.out.println(ThreeDesUtil.decode("DC143706E0E49BC4"));
    }
}
